#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <sqlite3.h>
#include <filesystem>
#include <MQ_Virtual_Engine/exchangeClass.hpp>

using namespace MY_MQ;



// Test Fixture for ExchangeManager tests
class ExchangeManagerTest : public ::testing::Test {
protected:
    std::string dbPath;

    void SetUp() override {
        dbPath =  "./test_exchange.db";
        if( std::filesystem::exists(dbPath))
        {
            std::filesystem::remove(dbPath);
        }
    }

    void TearDown() override {
        std::filesystem::remove(dbPath);
    }
};

// Test declaring an exchange
TEST_F(ExchangeManagerTest, DeclareExchange) {
    
    ExchangeManager manager("./test_exchange.db");
    manager.declareExchange("test_exchange", MQ_Protobuf::ExchangeType::DIRECT);
    ASSERT_TRUE(manager.exsits("test_exchange"));
    ASSERT_EQ(manager.size(), 1);
    manager.clear();
}

// Test declaring an exchange that already exists
TEST_F(ExchangeManagerTest, DeclareExistingExchange) {
    ExchangeManager manager(dbPath);
    
    ASSERT_TRUE(manager.declareExchange("test_exchange", MQ_Protobuf::ExchangeType::FANOUT));
    ASSERT_FALSE(manager.declareExchange("test_exchange", MQ_Protobuf::ExchangeType::DIRECT));
    ASSERT_EQ(manager.size(), 1);
    manager.clear();
}

// Test removing an exchange
TEST_F(ExchangeManagerTest, RemoveExchange) {
    ExchangeManager manager(dbPath);
    
    manager.declareExchange("test_exchange", MQ_Protobuf::ExchangeType::TOPIC);
    ASSERT_TRUE(manager.removeExchange("test_exchange"));
    ASSERT_FALSE(manager.exsits("test_exchange"));
    ASSERT_EQ(manager.size(), 0);
}

// Test removing a non-existent exchange
TEST_F(ExchangeManagerTest, RemoveNonExistentExchange) {
    ExchangeManager manager(dbPath);
    
    ASSERT_FALSE(manager.removeExchange("non_existent_exchange"));
    ASSERT_EQ(manager.size(), 0);
}

// Test recovering exchanges from the database
TEST_F(ExchangeManagerTest, RecoverExchanges) {
    {
        ExchangeManager manager(dbPath);
        manager.declareExchange("exchange1", MQ_Protobuf::ExchangeType::DIRECT);
        manager.declareExchange("exchange2", MQ_Protobuf::ExchangeType::FANOUT);
    }

    // Recreate the manager to trigger recovery
    ExchangeManager recoveredManager(dbPath);
    ASSERT_FALSE(recoveredManager.exsits("exchange1"));
    ASSERT_FALSE(recoveredManager.exsits("exchange2"));
    ASSERT_EQ(recoveredManager.size(), 0);
}

// Test clearing all exchanges, including persistent ones
TEST_F(ExchangeManagerTest, ClearExchanges) {
    ExchangeManager manager(dbPath);
    
    manager.declareExchange("exchange1", MQ_Protobuf::ExchangeType::DIRECT);
    manager.declareExchange("exchange2", MQ_Protobuf::ExchangeType::FANOUT);
    
    manager.clear();
    
    ASSERT_EQ(manager.size(), 0);
    ASSERT_FALSE(manager.exsits("exchange1"));
    ASSERT_FALSE(manager.exsits("exchange2"));
}

// Test clearing only temporary exchanges
TEST_F(ExchangeManagerTest, ClearTemporaryExchanges) {
    ExchangeManager manager(dbPath);
    
    manager.declareExchange("exchange1", MQ_Protobuf::ExchangeType::DIRECT, false);
    manager.declareExchange("exchange2", MQ_Protobuf::ExchangeType::FANOUT, true);
    
    manager.clearTmpExchange();
    
    ASSERT_EQ(manager.size(), 0);
}



int main(int argc, char **argv) {
    fmtlog::setHeaderPattern("{s} \t| {t} \t| {l} \t| {YmdHMS} \t| {g} \t| \n\t:");
    fmtlog::startPollingThread(12);
    //启用测试
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}